package com.zjitc.service.imp;

import com.github.pagehelper.PageHelper;
import com.google.gson.Gson;
import com.zjitc.dao.*;
import com.zjitc.model.*;
import com.zjitc.service.OrderService;
import com.zjitc.service.ProductService;
import com.zjitc.utils.Paging;
import com.zjitc.utils.Utils;

import com.zjitc.utils.redis.MyRedis;

import java.util.Set;

import org.apache.log4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * Create by IntelliJ IDEA
 *
 * @author: lhl
 * @date-Time: 2018/4/5 0005
 * @description:
 */
@Service
public class ProductServiceImpl implements ProductService {
    private static Logger logger = Logger.getLogger(ProductServiceImpl.class);
    @Autowired
    private ProductDao dao;
    @Autowired
    private CarDao carDao;
    @Autowired
    private OrderDao orderDao;
    @Autowired
    private UserDao userDao;
    @Autowired
    private OrderItemDao orderItemDao;
    @Autowired
    private OrderService orderService;
    @Autowired
    private MyRedis redis;

    public Product jsonToObject(String str) {
        Gson gson = new Gson();
        Product product = gson.fromJson(str, Product.class);
        return product;
    }

    public String objectToJson(Product product) {
        Gson gson = new Gson();
        String s = gson.toJson(product);
        return s;
    }

    @Override
    public List<Product> findHot() {
        List<Product> products = redis.allProducts();
        if (products != null && !"".equals(products)) {
            if (products.size() != 0) {
                ArrayList productHotList = new ArrayList();
                Product product = null;
                for (int i = 0; i < products.size(); i++) {
                    product = products.get(i);
                    if (product.getIsHot() == 1 && product.getFlag() != 1) {
                        productHotList.add(product);
                    }
                }
                ArrayList tem = new ArrayList();
                int productSize = 9;
                if (productHotList.size() > productSize) {
                    for (int j = 0; j < productSize; j++) {
                        tem.add(productHotList.get(j));
                    }
                } else {
                    for (int j = 0; j < productHotList.size(); j++) {
                        tem.add(productHotList.get(j));
                    }
                }
                return tem;
            }
        }
        logger.debug("ProductServiceImpl中redis为空....及时处理");
        List<Product> hot = dao.findHot();
        return hot;
    }

    @Override
    public List<Product> findNest() {
        List<Product> products = getNest();
        if (products != null && !"".equals(products)) {
            if (products.size() != 0) {
                List<Product> productNestList = new ArrayList();
                //不是秒杀产品的最新产品
                for (Product product : products) {
                    if (product.getFlag() == 0) {
                        productNestList.add(product);
                    }
                }
                int productSize = 9;
                List<Product> nestLimit = new ArrayList<>();
                if (productNestList.size() > productSize) {
                    for (int i = 0; i < productSize; i++) {
                        nestLimit.add(productNestList.get(i));
                    }
                } else {
                    return productNestList;
                }
                return nestLimit;
            }
        }

        logger.debug("ProductServiceImpl中redis为空....及时处理");
        List<Product> nest = dao.findNest();
        return nest;
    }

    public List<Product> getNest() {
        List<Product> products = redis.allProducts();
        if (products != null && !"".equals(products)) {
            ArrayList<Long> list1 = new ArrayList();
            ArrayList<String> list2 = new ArrayList();
            if (products != null) {
                for (Product product : products) {
                    if (product.getDate() != null && product.getPid() != null) {
                        list1.add(product.getDate().getTime());
                        list2.add(product.getPid());
                    }
                }
            }
            Long[] nestByDate = new Long[list1.size()];
            String[] arrayPid = new String[list2.size()];
            // List转换成数组
            for (int i = 0; i < list2.size(); i++) {
                nestByDate[i] = list1.get(i);
                arrayPid[i] = list2.get(i);
            }
            sortArrary(nestByDate, arrayPid);
            List<Product> productsList = new ArrayList<>();
            Gson gson = new Gson();
            for (int i = 0; i < arrayPid.length; i++) {
                String s = redis.getOneById("products", arrayPid[i]);
                if (s != null && !"".equals(s)) {
                    productsList.add(gson.fromJson(s, Product.class));
                }
            }
            return productsList;
        }
        return null;
    }

    public static void sortArrary(Long[] a, String[] b) {
        int j, k = a.length;
        //发生了交换就为true, 没发生就为false，第一次判断时必须标志位true。
        boolean flag = true;
        while (flag) {
            //每次开始排序前，都设置flag为未排序过
            flag = false;
            for (j = 1; j < k; j++) {
                //前面的数字小于后面的数字就交换
                if (a[j - 1] < a[j]) {
                    //交换a[j-1]和a[j]
                    Long temp1;
                    String temp2;
                    temp1 = a[j - 1];
                    a[j - 1] = a[j];
                    a[j] = temp1;

                    temp2 = b[j - 1];
                    b[j - 1] = b[j];
                    b[j] = temp2;

                    //表示交换过数据;
                    flag = true;
                }
            }
            //减小一次排序的尾边界
            k--;
            //end while
        }
        //end
    }

    @Override
    public Product findByPid(String pid) {
        String s = redis.getOneById("products", pid);
        if (s != null && !"".equals(s)) {
            return jsonToObject(s);
        } else {
            return dao.findByPid(pid);
        }
    }

    @Override
    public List<Product> findByCid(String cid, int pageId, int pageSize) {
        PageHelper.startPage(pageId, pageSize);
        List<Product> products = dao.findByCid(cid);
        return products;
    }

    @Override
    public List<Product> findProducts(int pageNum, int pageSize) {
        PageHelper.startPage(pageNum, pageSize);
        List<Product> products = dao.findProducts();
        return products;
    }

    /**
     * 模糊查询
     */
    public List search(String name, List list) {
        List results = new ArrayList();
        Pattern pattern = Pattern.compile(name);
        for (int i = 0; i < list.size(); i++) {
            Matcher matcher = pattern.matcher(((Product) list.get(i)).getName());
            if (matcher.find()) {
                results.add(list.get(i));
            }
        }
        return results;
    }

    @Override
    public Page<Product> findLike(String name, int pageIndex, int count) {
        Gson gson = new Gson();
        List<Product> products = redis.allProducts();
        if (products != null && !"".equals(products)) {
            if (products.size() != 0) {
                List<Product> search = search(name, products);
                for (Product product : search) {
                    redis.zadd(name, product.getDate().getTime(), gson.toJson(product));
                }
                Long aCatch = redis.zcard(name);
                int totalCount = aCatch.intValue();
                int pageCount = (int) Math.ceil(totalCount / count);

                Set<String> set = redis.zrange(name, count * pageIndex, count * pageIndex + count - 1);
                List<Product> temProducts = new ArrayList<Product>();
                for (String str : set) {
                    Product product = gson.fromJson(str, Product.class);
                    temProducts.add(product);
                }
                Paging<Product> paging = new Paging<>();
                Page page = paging.getPage(pageIndex, pageCount, temProducts);
                return page;
            }
        }
        int sqlCount = dao.countName(name);
        int pageCount = (int) Math.ceil(sqlCount / count);
        Paging<Product> paging = new Paging<>();
        List<Product> productList = dao.findLikeByName(name, pageIndex * count, count);
        Page page = paging.getPage(pageIndex, pageCount, productList);
        return page;
    }

    @Override
    public Page<Product> findByFlag(int flag, int pageIndex, int count) {
        boolean b = redis.exists("skillProducts");
        if (b) {
            redis.del("skillProducts");
        }
        List<Product> productList = redis.allProducts();
        Gson gson = new Gson();
        if (productList.size() != 0 && !"".equals(productList)) {
            if (productList.size() != 0) {
                for (Product product : productList) {
                    if (product.getFlag() != null && flag == product.getFlag()) {
                        redis.zadd("skillProducts", product.getDate().getTime(), gson.toJson(product));
                    }
                }
                boolean c = redis.exists("skillProducts");
                if (c) {
                    Long aCatch = redis.zcard("skillProducts");
                    int totalCount = aCatch.intValue();
                    int pageCount = (int) Math.ceil(totalCount / count);

                    Set<String> set = redis
                            .zrange("skillProducts", count * pageIndex, count * pageIndex + count - 1);
                    List<Product> temProducts = new ArrayList<Product>();
                    for (String str : set) {
                        Product product = gson.fromJson(str, Product.class);
                        temProducts.add(product);
                    }
                    Paging<Product> paging = new Paging<>();
                    Page page = paging.getPage(pageIndex, pageCount, temProducts);
                    return page;
                }
            }
        }
        int sqlCount = dao.flagCount();
        int pageCount = (int) Math.ceil(sqlCount / count);
        Paging<Product> paging = new Paging<>();
        List<Product> products = dao.findFlagLimit(flag, pageIndex, count);
        Page page = paging.getPage(pageIndex, pageCount, products);
        return page;
    }

    @Override
    public void add(Product product) {
        product.setPid(Utils.getUUID());
        product.setDate(new Date());
        if (product.getSkillCount() == null) {
            product.setSkillCount(0);
        }
        dao.add(product);
        redis.addCathc("products", product.getPid(), objectToJson(product));
    }

    @Override
    public String deleteByPid(String pid) {
        /**
         * 购物车中含有该商品，直接删除，
         * 用户订单中含有该商品，判断，已付款和未付款遍历订单删除该商品
         */
        carDao.delete(pid);
        List<User> all = userDao.findAll();
        for (User user : all) {
            List<Order> orders = orderDao.findByUid(user.getUid());
            for (Order order : orders) {
                if (order.getState() == 0 || order.getState() == -1) {
                    List<OrderItem> items = orderItemDao.findByOid(order.getOid());
                    if (items.size() > 1) {
                        for (OrderItem item : items) {
                            if (item.getPid().equals(pid)) {
                                orderItemDao.deleteByOid(order.getOid());
                            }
                        }
                    }
                    //如果只有一个商品，，就把该订单删除
                    if (items.size() == 1) {
                        orderService.deleteByOid(order.getOid());
                    }
                }
                //已经付款，，该商品暂时不能删除，妨碍退款
                if (order.getState() == 1) {
                    List<OrderItem> items = orderItemDao.findByOid(order.getOid());
                    if (items != null) {
                        for (OrderItem item : items) {
                            if (item.getPid().equals(pid)) {
                                return Integer.toString(1);
                            }
                        }
                    }
                }
            }
        }
        dao.delete(pid);
        redis.deleteById("products", pid);
        return pid;
    }

    @Override
    public void update(Product product) {

        if (product.getImage() == null) {
            Product one = dao.findByPid(product.getPid());
            product.setImage(one.getImage());
        }
        if (product.getSkillCount() > product.getProductCount()) {
            product.setSkillCount(product.getProductCount());
        }
        product.setDate(new Date());
        dao.update(product);
        redis.alertById("products", product.getPid(), objectToJson(product));
    }

    public int produceProductsByCid(String cid) {
        redis.del(cid + "productPage");
        List<Product> products = redis.allProducts();
        Gson gson = new Gson();
        if (products.size() != 0) {
            for (Product product : products) {
                if (cid != null && cid.equals(product.getCid())) {
                    redis.zadd(cid + "productPage", product.getDate().getTime(), gson.toJson(product));

                }
            }
            return -1;
        }
        return 1;
    }

    @Override
    public Page<Product> findByCatchByCid(String cid, int pageIndex, int count) {
        int i = produceProductsByCid(cid);
        if (i == 1) {
            int sqlCount = dao.count(cid);
            int pageCount = (int) Math.ceil(sqlCount / count);
            Paging<Product> paging = new Paging<>();
            List<Product> productList = dao.findLimitByCid(cid, pageIndex * count, count);
            Page page = paging.getPage(pageIndex, pageCount, productList);
            return page;
        } else {
            Long aCatch = redis.zcard(cid + "productPage");
            int totalCount = aCatch.intValue();
            int pageCount = (int) Math.ceil(totalCount / count);
            Set<String> set = redis
                    .zrange(cid + "productPage", count * pageIndex, count * pageIndex + count - 1);
            List<Product> products = new ArrayList<Product>();
            Gson gson = new Gson();
            for (String str : set) {
                Product product = gson.fromJson(str, Product.class);
                if (product.getFlag() != 1) {
                    products.add(product);
                }
            }

            Paging<Product> paging = new Paging<>();
            Page page = paging.getPage(pageIndex, pageCount, products);
            return page;
        }
    }

}
